﻿using System;
using System.Collections.Generic;
using System.Text;
using ExcelLibrary.Office.Excel;
using System.IO;


namespace SeleniumOrderPathRunner {
    public class ExcelLogger {
        
        #region field variables
        private Workbook workbook;
        private Worksheet datasheet;
        private Worksheet aggregatorsheet;
        private int currentLogLine;
        private int currentOrderpathLine;
        private String file;
        #endregion


        public ExcelLogger(String logPath, SeleniumServer.OrderAppEnvironment env, SeleniumServer.Browser browser ) {
            //create template structure
            workbook = new Workbook();
            datasheet = new Worksheet("Raw results");
            aggregatorsheet = new Worksheet("Aggregated results");
            ColorPalette palette = new ColorPalette();
            currentLogLine = 0;
            currentOrderpathLine = 0;
            file = logPath + Path.DirectorySeparatorChar + "seleniumLog-" + DateTime.Now.ToString("yyyy'-'MM'-'dd'_'HH'-'mm'-'ss") + ".xls";

            
            //set up raw data sheet
            datasheet.Cells[0, 0] = new Cell("Orderpath Name");
            //datasheet.Cells[0, 0].BackColor = palette[7];//color doesn't work
            datasheet.Cells.ColumnWidth[0] = 4000;
            datasheet.Cells[0, 1] = new Cell("Orderpath URL");
            datasheet.Cells.ColumnWidth[1] = 18500;
            datasheet.Cells[0, 2] = new Cell("Orderpath Trial");
            datasheet.Cells.ColumnWidth[2] = 4000;
            datasheet.Cells[0, 3] = new Cell("Orderpath Skin");
            datasheet.Cells.ColumnWidth[3] = 5000;
            datasheet.Cells[0, 4] = new Cell("Test Name");
            datasheet.Cells.ColumnWidth[4] = 13500;
            datasheet.Cells[0, 5] = new Cell("Test Success");
            datasheet.Cells.ColumnWidth[5] = 3800;

            //set up aggregator sheet
            aggregatorsheet.Cells[0, 0] = new Cell("Aggregation");
            aggregatorsheet.Cells[1, 0] = new Cell(@"=COUNTIFS(INDIRECT(""'Raw results'!""&B2&"":""&B2),  C2,        INDIRECT(""'Raw results'!""&D2&"":""&D2),  E2,              INDIRECT(""'Raw results'!""&F2&"":""&F2),  G2)");
            aggregatorsheet.Cells.ColumnWidth[0] = 5000;
            aggregatorsheet.Cells[0, 1] = new Cell("Column1");
            aggregatorsheet.Cells[1, 1] = new Cell("C");
            aggregatorsheet.Cells.ColumnWidth[1] = 4000;
            aggregatorsheet.Cells[0, 2] = new Cell("MatchValueForColumn1");
            aggregatorsheet.Cells[1, 2] = new Cell("NOTRIAL");
            aggregatorsheet.Cells.ColumnWidth[2] = 8000;
            aggregatorsheet.Cells[0, 3] = new Cell("Column2");
            aggregatorsheet.Cells[1, 3] = new Cell("F");
            aggregatorsheet.Cells.ColumnWidth[3] = 4000;
            aggregatorsheet.Cells[0, 4] = new Cell("MatchValueForColumn2");
            aggregatorsheet.Cells[1, 4] = new Cell("PASS");
            aggregatorsheet.Cells.ColumnWidth[4] = 8000;
            aggregatorsheet.Cells[0, 5] = new Cell("Column3");
            aggregatorsheet.Cells[1, 5] = new Cell("E");
            aggregatorsheet.Cells.ColumnWidth[5] = 4000;
            aggregatorsheet.Cells[0, 6] = new Cell("MatchValueForColumn3");
            aggregatorsheet.Cells[1, 6] = new Cell("Create valid subscription");
            aggregatorsheet.Cells.ColumnWidth[6] = 8000;
            
            //=COUNTIFS(INDIRECT("'Raw results'!"&B2&":"&B2),  C2,        INDIRECT("'Raw results'!"&D2&":"&D2),  E2,              INDIRECT("'Raw results'!"&F2&":"&F2),  G2)

            Worksheet orderpathList = new Worksheet("Orderpath data");
            orderpathList.Cells[0, 0] = new Cell("Orderpath Name");
            //datasheet.Cells[0, 0].BackColor = palette[7];
            orderpathList.Cells.ColumnWidth[0] = 4000;
            orderpathList.Cells[0, 1] = new Cell("Orderpath URL");
            orderpathList.Cells.ColumnWidth[1] = 19500;
            orderpathList.Cells[0, 2] = new Cell("Orderpath Skin");
            orderpathList.Cells.ColumnWidth[2] = 5500;

            workbook.Worksheets.Add(datasheet);
            workbook.Worksheets.Add(aggregatorsheet);
            workbook.Worksheets.Add(orderpathList);

            workbook.Save(file);
        }


        public void addOrderpathData(String name, String URL, String skin) {
            try {
                workbook.Worksheets[2].Cells[currentOrderpathLine + 1, 0] = new Cell(name);
                workbook.Worksheets[2].Cells[currentOrderpathLine + 1, 1] = new Cell(URL);
                workbook.Worksheets[2].Cells[currentOrderpathLine + 1, 2] = new Cell(skin);
                
            } catch (Exception e) {
                Console.WriteLine(e.Message);
            }
            try {
                workbook.Save(file);
            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }
            currentOrderpathLine++;
        }



        /// <summary>
        /// Stores data in temporary buffer to be written to a file later
        /// </summary>
        /// <param name="lb"></param>
        /// <param name="orderpath"></param>
        /// <param name="testName"></param>
        /// <param name="success"></param>
        public void addTestResults(ref LogBuffer lb, OrderPath orderpath, String testName, bool success) {
            lb.Orderpaths.AddLast(orderpath);
            lb.TestNames.AddLast(testName);
            lb.Successes.AddLast(success);
        }



        /// <summary>
        /// logs xls data from a buffer to xls file
        /// </summary>
        /// <param name="lb"></param>
        /// <param name="orderpath"></param>
        /// <param name="testName"></param>
        /// <param name="success"></param>
        public void addTestResults(LogBuffer lb) {
            if (lb.Orderpaths.Count == 0) {
                return;
            }
            try {
                IEnumerator<OrderPath> orderpaths = lb.Orderpaths.GetEnumerator();
                IEnumerator<String> testNames     = lb.TestNames.GetEnumerator();
                IEnumerator<bool> successes       = lb.Successes.GetEnumerator();

                for (int i = 0; i < lb.Orderpaths.Count; i++) {
                    orderpaths.MoveNext();
                    testNames.MoveNext();
                    successes.MoveNext();

                    workbook.Worksheets[0].Cells[currentLogLine + 1, 0] = new Cell(orderpaths.Current.Name);
                    workbook.Worksheets[0].Cells[currentLogLine + 1, 1] = new Cell(orderpaths.Current.URL);
                    workbook.Worksheets[0].Cells[currentLogLine + 1, 2] = new Cell(trialBoolToString(orderpaths.Current.Trial));
                    workbook.Worksheets[0].Cells[currentLogLine + 1, 3] = new Cell(orderpaths.Current.Skin.ToString());
                    workbook.Worksheets[0].Cells[currentLogLine + 1, 4] = new Cell(testNames.Current);
                    workbook.Worksheets[0].Cells[currentLogLine + 1, 5] = new Cell(successBoolToString(successes.Current));
                    currentLogLine++;
                }
                
            } catch (Exception e) {
                Console.WriteLine(e.Message);
            }
            try {
                workbook.Save(file);
            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }
            
        }



        /// <summary>
        /// Workaround for excel which handles 'TRUE' and 'FALSE' in weird ways that mess up the matching function
        /// Instead, use more specific wording for the bools
        /// </summary>
        /// <param name="isTrial"></param>
        /// <returns></returns>
        private String trialBoolToString(bool isTrial) {
            if (isTrial) {
                return "TRIAL";
            } else {
                return "NOTRIAL";
            }
        }
        private String successBoolToString(bool isSuccessful) {
            if (isSuccessful) {
                return "PASS";
            } else {
                return "FAIL";
            }
        }
    }
}
